#include "TPlaca.h"
#include "TComando.h"

#define CMD_SALIDA "QUIT"

#define MAIN_OK 0
#define MAIN_ERR_MEMORIA 1

#define MSG_ERR_CMDDESCONOCIDO "ERROR: Comando desconocido. Escriba 'HELP' para obtener ayuda.\n\n"
#define MSG_HELP " CONNECT <D>            Conecta la placa de direccion <D> al medio\
                \n DISCONNECT <D>         Desconecta del medio la placa de direccion <D>\
                \n SEND <O> <D> <MENSAJE> Envia <MENSAJE> desde <O> a <D>\
                \n RECV                   Muestra el contenido del buffer de las placas conectadas al medio\
                \n HELP                   Muestra este texto\n\n"
#define MSG_BIENVENIDA "TP1: Abstraccion\nSimulador de Red de Computadoras\n\nEscriba 'HELP' para obtener ayuda.\n\n"

int interpretar_comando(TComando* comando, char* operacion, TMedio* medio) {
	char* argumentos[LONGITUD_MAXIMA];
	TPlaca* placas_conectadas[MAX_PLACAS];
	TPlaca* placa;
	void* destino;
	char* dir;
	TDireccion direccion;
	int i=0,k = 0, j = 0,a = 0;

    placa = (TPlaca*)malloc(sizeof(TPlaca));
	*argumentos = (char*) malloc(LONGITUD_MAXIMA);
	while(strcasecmp(operacion, CMD_SALIDA)){

        Comando_Leer(comando);
        Comando_ObtenerOperacion(comando, &operacion);

    if (!(strcasecmp(operacion,"QUIT")==0) && !(strcasecmp(operacion,"HELP")==0) && !(strcasecmp(operacion,"RECV")==0)){
        parsear_argumentos(comando, argumentos);
    }
	if (!strcasecmp(operacion, "CONNECT")) {
		dir = (char*)malloc(100);
		direccion = (TDireccion)atoi(dir);
		/* free(dir); Lo comento porque me da error */
	
		if (!Placa_Crear(placa, direccion)) {
			if (!Placa_Conectar(placa, medio)) {
				placas_conectadas[i] = placa;
				i++;
			}
		}	}
	else if (!strcasecmp(operacion, "DISCONNECT")) {
            if ((int)Medio_ContarConectadas(medio) > 0){
                Comando_ObtenerArgumentos(comando,0,argumentos);
                while (k < Medio_ContarConectadas(medio) - 1){
                    if (Placa_GetDireccion(placas_conectadas[k]) == atoi (argumentos)){
                        Placa_Desconectar(placas_conectadas[k]);
                        i--;
                        for (j=k; j < Medio_ContarConectadas(medio);j++){
                            placas_conectadas[j] = placas_conectadas [j+1];
                        }
                        a = 0;
                    } else
                        k++;
                }
                if (!a){
                    placas_conectadas[Medio_ContarConectadas(medio) - 1] = NULL;
                    printf("OK");
                }
                else
                    if (placas_conectadas[Medio_ContarConectadas(medio) - 1] = atoi (argumentos)) {
                        Placa_Desconectar(placas_conectadas[Medio_ContarConectadas(medio) - 1]);
                        placas_conectadas [Medio_ContarConectadas(medio  - 1)] = NULL;
                        i--;
                        printf ("OK");
                    }
                    else
                        printf ("ERROR");
            }
            else
                printf ("ERROR");
    }
	else if (!strcasecmp(operacion, "SEND")) {
	    Placa_Enviar (placa,Comando_ObtenerArgumentos(comando, 2, *argumentos),(size_t)strlen(Comando_ObtenerArgumentos(comando, 0, *argumentos)),Comando_ObtenerArgumentos(comando, 1, *argumentos));
	}
	else if (!strcasecmp(operacion, "RECV")) {
            destino = (char*)malloc(MTU);
            for (i = 0; i < Medio_ContarConectadas(medio); i++){
                if (Placa_Leer (placas_conectadas[i],destino)){
                    printf ("Mensaje a leer de la placa con direccion %d/n/n",Placa_GetDireccion(placas_conectadas[i]));
                    printf ("%s/n/n",(char*)destino);
                }
                else
                    printf ("No hay mensaje en la placa de direccion %d/n/n",Placa_GetDireccion(placas_conectadas[i]));
            }
            free(destino);
	}
	else if (!strcasecmp(operacion, "HELP")) {
		printf(MSG_HELP);
	}
	else if (!strcasecmp(operacion, "QUIT")){
        return MAIN_OK;
	}
	else {
		printf(MSG_ERR_CMDDESCONOCIDO);
	}
	}
	free(placa);
    return MAIN_OK;
}

int mostrar_consola() {
    TMedio* medio;
	TComando comando;
	char* operacion[LONGITUD_MAXIMA];

    medio = (TMedio*)malloc(sizeof(TMedio));
	Medio_Crear(medio);

	if (Comando_Crear(&comando, LONGITUD_MAXIMA) != MAIN_OK)
		return MAIN_ERR_MEMORIA;

	*operacion = (char*) malloc(LONGITUD_MAXIMA);

    interpretar_comando(&comando, *operacion, medio);

    Medio_Destruir(medio);
	free(medio);
	Comando_Destruir(&comando);
	free(*operacion);

	return MAIN_OK;
}

int main(int argc, char** argv) {
	printf(MSG_BIENVENIDA);
	mostrar_consola();
    return MAIN_OK;
}

/*** Empiezan casos de prueba ***/
/*int test() {
	int codigo_error;
	TMedio medio;
	TPlaca placa;
	codigo_error = Medio_Crear(&medio);
	printf("main: &placa = %d\n", &placa);
	printf("main: Medio_Crear(medio) devolvio %d\n", codigo_error);
	printf("main: medio.cantidad_placas_conectadas = %d\n", medio.cantidad_placas_conectadas);

	codigo_error = Placa_Crear(&placa, 124);
	printf("main: Placa_Crear(placa) devolvio %d\n", codigo_error);

	printf("main: placa.direccion = %d\n", Placa_GetDireccion(&placa));

	codigo_error = Medio_Conectar(&medio, &placa);
	printf("main: Medio_Conectar(medio, placa) devolvio %d\n", codigo_error);
	printf("main: medio.placas_conectadas[0]: %d\n", Placa_GetDireccion(p));*/ /* No se por que pincha esto!
	codigo_error = Placa_Recibir(&placa, "123 122 Hola que tal", 100);
	printf("main: Placa_Recibir salio con codigo %d\n", codigo_error);




	return MAIN_OK;
}/*** Fin casos de prueba ***/
